#include "discovery_meter.h"
#include <string.h>
//#include "utils.h"

#define ARRAY_SIZE(array)   (sizeof(array)/sizeof(array[0]))

static const uint8_t _child_parent[][2]= {
    0x33, 0x34,
    0x44, 0x34,
    0x88, 0x89,
    0x99, 0x89,
    0x00, 0x01,
    0x11, 0x01,
    0x22, 0x24,
    0x34, 0x24,
    0x55, 0x56,
    0x66, 0x56,
    0x77, 0x79,
    0x89, 0x79,
    0x01, 0x04,
    0x24, 0x04,
    0x56, 0x59,
    0x79, 0x59,
    0x04, 0x09,
    0x59, 0x09,
};

static const uint8_t _parent_child[][2]= {
    0x09, 0x04,
    0x04, 0x01,
    0x59, 0x56,
    0x01, 0x00,
    0x24, 0x22,
    0x56, 0x55,
    0x79, 0x77,
    0x34, 0x33,
    0x89, 0x88,
};

static const uint8_t _brother_bro[][2]= {
    0x04, 0x59,
    0x01, 0x24,
    0x56, 0x79,
    0x00, 0x11,
    0x22, 0x34,
    0x55, 0x66,
    0x77, 0x89,
    0x33, 0x44,
    0x88, 0x99,
};


static char _get_parent(char my_name)
{
    unsigned int i;

    for(i = 0; i < ARRAY_SIZE(_child_parent); i++)
    {
        if((uint8_t)_child_parent[i][0] == (uint8_t)my_name)
        {
            return _child_parent[i][1];
        }
    }
    return -1;//没有父节点（本身就是顶级节点）
}

static char _get_little_brother(char my_name)
{
    unsigned int i;

    for(i = 0; i < ARRAY_SIZE(_brother_bro); i++)
    {

        if((uint8_t)_brother_bro[i][0] == (uint8_t)my_name)
        {
            //printf("my_name = %02x, brotherbro[%d][0]= %02X\r\n", (uint8_t)my_name, i, brotherbro[i][0]);
            return _brother_bro[i][1];
        }
    }
    return -1;
}

static char _get_first_child(char my_name)
{
    unsigned int i;

    for(i = 0; i < ARRAY_SIZE(_parent_child); i++)
    {
        if((uint8_t)_parent_child[i][0] == (uint8_t)my_name)
        {
            return _parent_child[i][1];
        }
    }
    return -1;
}


static char _get_nearest_brother_of_family(char my_name)//该函数也可用查表法实现
{
    char  bro_tmp;
    while(1)
    {
        bro_tmp = _get_little_brother(my_name);
        if(bro_tmp == (char)-1)
        {
            char father_tmp = _get_parent(my_name);
            if(father_tmp == (char)-1)
                return -1;
            else
            {
                my_name = father_tmp;
                continue;
            }

        }
        return bro_tmp;
    }
}


static char _get_nearset_brother_of_whole_familys(unsigned char *match, int *cur_idx)
{
    while(1)
    {
        char bro_tmp = _get_nearest_brother_of_family(match[(*cur_idx)]);//找本家庭的最近的弟弟
        if(bro_tmp == (char)-1)
        {
            match[(*cur_idx)] = 0x09;
            (*cur_idx)--;
            if((*cur_idx) < 0)
                return -1;
        }
        else
        {
            match[(*cur_idx)] = (unsigned char)bro_tmp;
            return 0;
        }
    }
}


static char _get_nearset_first_child_of_whole_familys( unsigned char *match, int *cur_idx)
{
    while(1)
    {
        char child_tmp = _get_first_child(match[(*cur_idx)]);
        if(child_tmp == (char)-1)
        {
            if((*cur_idx) == DISCOVERY_MAX_LAYER - 1)
            {
                return -1;//最底层没有孩子
            }
            (*cur_idx)++;
        }
        else
        {
            match[(*cur_idx)] = child_tmp;
            return 0;
        }
    }
}
static uint8_t  _cnt_09_in_wildcard_reverse(uint8_t str[])
{
    uint8_t cnt = 0;
    int i=0;
    for(i = DISCOVERY_MAX_LAYER - 1; i > 0; i--)
    {
        if(str[i] == 0x09)
            cnt++;
        else
            break;

    }
    return cnt;
}

void  discovery_init_and_start(discover_meter_event* discover_event, int device_nums)
{
    char wildcard_addr[DISCOVERY_MAX_LAYER] = {0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09};

    discover_event->status = IS_SEARCHING;
    discover_event->res = SEARCH_NONE;
    discover_event->meter_nums = device_nums;
    discover_event->found_nums = 0;
    memcpy(discover_event->wildcard,wildcard_addr,sizeof(wildcard_addr));
}

void discovery_get_none_meter(discover_meter_event* discover_event)
{
    discover_event->res = SEARCH_NONE;
}

void discovery_get_one_meter(discover_meter_event* discover_event)
{
    discover_event->res = SEARCH_SINGLE;
}

void discovery_meters_collide(discover_meter_event* discover_event)
{
    discover_event->res = SEARCH_COLLIDE;
}

int  discovery_is_searching(discover_meter_event* discover_event)
{
    if(IS_SEARCHING == discover_event->status)
        return 1;
    else
        return 0;
}

void  discovery_meter_get_next_wildcard(discover_meter_event* discover_event,uint8_t next_wildcard[])
{
    static uint8_t last_wildcard_0;
	int cnt_09 = _cnt_09_in_wildcard_reverse(discover_event->wildcard);
	int cur_idx = DISCOVERY_MAX_LAYER - 1 - cnt_09;

    if(discover_event->res == SEARCH_NONE ||discover_event->res == SEARCH_SINGLE)
    {
        if(discover_event->res == SEARCH_SINGLE)
        {
            discover_event->found_nums++;
            if(discover_event->found_nums == discover_event->meter_nums)
            {
                discover_event->status = SEARCH_END;
                return ;
            }
        }
	    #if 0 
			if(cur_idx ==0)
			{
				if(discover_event->wildcard[0] <= 0x88)
				{
					discover_event->wildcard[0] += 0x11;
					last_wildcard_0 = discover_event->wildcard[0];
				}
				else
				{
					discover_event->status = SEARCH_END;
					return ;
				}
			}
			else
			{
				char ok = _get_nearset_brother_of_whole_familys(discover_event->wildcard,&cur_idx);
				if(ok == (char)-1)
				{
					discover_event->status = SEARCH_END;
					return ;
				}
				else
				{
					int cur_idxx = DISCOVERY_ORDER - 1 - _cnt_09_in_wildcard_reverse(discover_event->wildcard);
					if(cur_idxx ==0)
					{
						discover_event->wildcard[0] = last_wildcard_0 +0x11;
						last_wildcard_0 = discover_event->wildcard[0];
					}
				}
			}
		#endif
		char ok = _get_nearset_brother_of_whole_familys(discover_event->wildcard,&cur_idx);
		if(ok == (char)-1)
		{
			discover_event->status = SEARCH_END;
			return ;
		}
	}
    else
    {
        _get_nearset_first_child_of_whole_familys(discover_event->wildcard,&cur_idx);
    }
    memcpy(next_wildcard,discover_event->wildcard,DISCOVERY_MAX_LAYER);
	
}


